package com.wurd.wurdAnalysis;

import org.thulac.base.POCGraph;
import org.thulac.base.SegmentedSentence;
import org.thulac.base.TaggedSentence;
import org.thulac.character.CBTaggingDecoder;
import org.thulac.manage.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class WurdAnalysis {

    static String user_specified_dict_name = null;
    static Character separator = '_';

    static int maxLen = 1024;

    static boolean useT2S = false;
    static boolean seg_only = true;
    static boolean useFilter = false;
    static String prefix = "models/";

    static POCGraph poc_cands = new POCGraph();
    static CBTaggingDecoder tagging_decoder = new CBTaggingDecoder();
    static Filter filter = null;
    static Preprocesser preprocesser = new Preprocesser();
    static Postprocesser nsDict = null;
    static Postprocesser idiomDict = null;
    static Postprocesser userDict = null;
    static Punctuation punctuation = null;
    static TimeWord timeword = null;
    static NegWord negword = null;
    static VerbWord verbword = null;

    static WurdAnalysis analysis = new WurdAnalysis();
    static boolean initial = false;

    public static WurdAnalysis getInstance() {
        if (!initial) {
            analysis.init();
        }
        return analysis;
    }

    public static void getInstance(String thulac_user_specified_dict_name, Character thulac_separator, boolean thulac_useT2S, boolean thulac_seg_only, boolean thulac_useFilter, String thulac_prefix) {
        user_specified_dict_name = thulac_user_specified_dict_name;
        separator = thulac_separator;
        useT2S = thulac_useT2S;
        seg_only=thulac_seg_only;
        useFilter = thulac_useFilter;
        if(thulac_prefix != null){
            prefix = thulac_prefix;
        }
    }

    private synchronized void init() {
        if (initial) {
            return;
        }
        try {
            if (seg_only) {
                tagging_decoder.threshold = 0;
                tagging_decoder.separator = separator;
                tagging_decoder.init((prefix + "cws_model.bin"), (prefix + "cws_dat.bin"), (prefix + "cws_label.txt"));
                tagging_decoder.setLabelTrans();
            } else {
                tagging_decoder.threshold = 10000;
                tagging_decoder.separator = separator;
                tagging_decoder.init((prefix + "model_c_model.bin"), (prefix + "model_c_dat.bin"), (prefix + "model_c_label.txt"));
                tagging_decoder.setLabelTrans();
            }

            preprocesser.setT2SMap((prefix + "t2s.dat"));
            nsDict = new Postprocesser((prefix + "ns.dat"), "ns", false);
            idiomDict = new Postprocesser((prefix + "idiom.dat"), "i", false);
            if (user_specified_dict_name != null) {
                userDict = new Postprocesser(user_specified_dict_name, "uw", true);
            }
            punctuation = new Punctuation((prefix + "singlepun.dat"));
            timeword = new TimeWord();
            negword = new NegWord((prefix + "neg.dat"));
            verbword = new VerbWord((prefix + "vM.dat"), (prefix + "vD.dat"));
            if (useFilter) {
                filter = new Filter((prefix + "xu.dat"), (prefix + "time.dat"));
            }
            initial = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public List<String> analysis(String inputStr, Reader input) throws IOException {
        List<String> result = new ArrayList<String>();
        if(input == null || inputStr == null){
            return result;
        }
        BufferedReader reader = new BufferedReader(input);
        StringBuilder sb = new StringBuilder(inputStr);
        String str = null;
        try {
            while((str = reader.readLine()) != null){
                sb.append(str);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        Vector<String> vec = getRaw(sb.toString());
        return analysis1(vec);
    }

    public List<String> analysis(Reader input) throws IOException {
        List<String> result = new ArrayList<String>();
        if (input == null) {
            return result;
        }
        BufferedReader reader = new BufferedReader(input);
        Vector<String> vec = getRaw(reader);
        return analysis1(vec);
    }

    public List<String> analysis(String str) throws IOException {
        List<String> result = new ArrayList<String>();
        if (str == null) {
            return result;
        }
        Vector<String> vec = getRaw(str);
        return analysis1(vec);
    }

    public List<String> analysis1(Vector<String> vec) throws IOException {
        List<String> result = new ArrayList<String>();
        SegmentedSentence segged = new SegmentedSentence();
        TaggedSentence tagged = new TaggedSentence();
        long startTime = System.currentTimeMillis();//获取当前时间
        String oiraw;
        String raw;
        for (int i = 0; i < vec.size(); i++) {
            oiraw = vec.get(i);
            if (useT2S) {
                String traw;
                traw = preprocesser.clean(oiraw, poc_cands);
                raw = preprocesser.T2S(traw);
            } else {
                raw = preprocesser.clean(oiraw, poc_cands);
            }
            if (raw.length() > 0) {
                if (seg_only) {
                    tagging_decoder.segment(raw, poc_cands, tagged);
                    tagging_decoder.get_seg_result(segged);
                    nsDict.adjust(segged);
                    idiomDict.adjust(segged);
                    punctuation.adjust(segged);
                    timeword.adjust(segged);
                    negword.adjust(segged);
                    if (userDict != null) {
                        userDict.adjust(segged);
                    }
                    if (useFilter) {
                        filter.adjust(segged);
                    }
                    for (int j = 0; j < segged.size(); j++) {
                        result.add(segged.get(j));
                    }
                } else {
                    tagging_decoder.segment(raw, poc_cands, tagged);
                    nsDict.adjust(tagged);
                    idiomDict.adjust(tagged);
                    punctuation.adjust(tagged);
                    timeword.adjustDouble(tagged);
                    negword.adjust(tagged);
                    verbword.adjust(tagged);
                    if (userDict != null) {
                        userDict.adjust(tagged);
                    }
                    if (useFilter) {
                        filter.adjust(tagged);
                    }
                    for (int j = 0; j < tagged.size(); j++) {
                        String segStr = tagged.get(j).word + tagged.get(j).separator + tagged.get(j).tag;
                        result.add(segStr);
                    }
                }
            }
        }
        long endTime = System.currentTimeMillis();
        System.out.println("程序运行时间：" + (endTime - startTime) + "ms");
        return result;

    }

    public static Vector<String> getRaw(BufferedReader reader) {
        StringBuilder sb = new StringBuilder();
        String ans = null;
        try {
            while ((ans = reader.readLine()) != null) {
                sb.append(ans);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return getRaw(sb.toString());
    }

    public static Vector<String> getRaw(String str) {
        String ans = str;
        Vector<String> ans_vec = new Vector<String>();
        if (ans == null) return ans_vec;
        if (str.length() > maxLen) {
            Pattern p = Pattern.compile(".*?[。？！；;!?]");
            Matcher m = p.matcher(ans);
            int num = 0, pos = 0;
            String tmp;
            while (m.find()) {
                tmp = m.group(0);
                if (num + tmp.length() > maxLen) {
                    ans_vec.add(ans.substring(pos, pos + num));
                    pos += num;
                    num = tmp.length();
                } else {
                    num += tmp.length();
                }
            }
            if (pos != ans.length()) ans_vec.add(ans.substring(pos));
        } else {
            ans_vec.add(ans);
        }
        return ans_vec;
    }

}
